﻿using System.Collections.Generic;
using Sebrae.Academico.InfraEstrutura.Core;
using Sebrae.Academico.InfraEstrutura.Core.UnitOfWork;
using Sebrae.Academico.Trilhas.Dominio.Classes;
using System.Linq;
using NHibernate.Linq;
using Sebrae.Academico.InfraEstrutura.Core.Helper;
using System;

namespace Sebrae.Academico.Trilhas.BM.Classes
{
    public class BMUsuarioTrilha : BusinessManagerBase
    {

        #region Atributos

        private RepositorioBase<UsuarioTrilha> repositorio;

        #endregion

        #region "Construtor"

        public BMUsuarioTrilha(IUnitOfWork unitOfWork)
        {
            repositorio = new RepositorioBase<UsuarioTrilha>(unitOfWork);
        }

        #endregion

        public UsuarioTrilha ObterPorId(int ID)
        {
            return repositorio.ObterPorID(ID);
        }

        public void Salvar(UsuarioTrilha pUsuarioTrilha)
        {
            repositorio.Salvar(pUsuarioTrilha);
        }

        public IList<UsuarioTrilha> ObterUsuarioTrilhas()
        {
            return repositorio.ObterTodos();
        }

        public void ExcluirUsuarioTrilha(UsuarioTrilha pUsuarioTrilha)
        {
            if (ValidarDependencias(pUsuarioTrilha))
                throw new Exception("Exclusão de registro negada. Existem Registros Dependentes desta Matrícula.");

            repositorio.Excluir(pUsuarioTrilha);
        }

        public bool ValidarDependencias(UsuarioTrilha pUsuarioTrilha)
        {
            ValidarInstancia(pUsuarioTrilha);
            UsuarioTrilha usuarioTrilha = (UsuarioTrilha)pUsuarioTrilha;

            return ((usuarioTrilha.ListaItemTrilhaParticipacao != null && usuarioTrilha.ListaItemTrilhaParticipacao.Count > 0) ||
                   (usuarioTrilha.ListaTrilhaAtividadeInformativaParticipacao != null && usuarioTrilha.ListaTrilhaAtividadeInformativaParticipacao.Count > 0));
        }

        public void VerificarCamposObrigatoriosDoFiltro(UsuarioTrilha pUsuarioTrilha)
        {
            ValidarInstancia(pUsuarioTrilha);

            if (pUsuarioTrilha.Trilha == null) throw new Exception("Trilha. Campo Obrigatório ");

            if (pUsuarioTrilha.TrilhaNivel == null) throw new Exception("Nível da Trilha. Campo Obrigatório ");
        }

        public void ValidarMatriculaTrilhaInformada(UsuarioTrilha pUsuarioTrilha)
        {
            // Validando se a instância do usuário trilha está nula.
            ValidarInstancia(pUsuarioTrilha);

            //Todo -> Implementar validação para os campos Obrigatórios
        }

        public IList<UsuarioTrilha> ObterPorFiltro(UsuarioTrilha pUsuarioTrilha)
        {

            IList<UsuarioTrilha> ListaUsuarioTrilha = null;

            try
            {
                var query = repositorio.Session.Query<UsuarioTrilha>();

                if (pUsuarioTrilha != null)
                {
                    if (pUsuarioTrilha.Trilha != null)
                        query = query.Where(x => x.Trilha.ID == pUsuarioTrilha.Trilha.ID);

                    if (pUsuarioTrilha.TrilhaNivel != null)
                        query = query.Where(x => x.TrilhaNivel.ID == pUsuarioTrilha.TrilhaNivel.ID);
                }

                /* O Fetch faz o inner join / left outer join para buscar os dados do usuario.
                   O método CriarSessionFactory da classe NHibernateHelper possui a instrução
                   .UseOuterJoin() para indicar ao NHibernate que o left outer join será utilizado 
                   nas queries */
                query = query.Fetch(x => x.Usuario);
                query = query.Fetch(x => x.NivelOcupacional);
                query = query.Fetch(x => x.StatusMatricula);

                ListaUsuarioTrilha = query.AsParallel().ToList<UsuarioTrilha>();
            }
            catch (System.Exception ex)
            {
                ExceptionHandler.TratarExcecao(ex);
            }

            return ListaUsuarioTrilha;

        }
    }
}
